//2024.01.22 18:41 星期一 晴

import {
  getNum,
  ObjectOnlyPushSet,
  toStringTypeCheck,
} from '../../../components/aaanewApp/global/global';
import { injectFactory } from '../../../components/aaanewApp/globalLib/global';
import { search_BigPolygon } from '../../TestJS/searchforBigestPolygon/searchforBigestPolygon';

let defaultArea_iFacObj = injectFactory('m_defaultArea');

let isArrayElInfo = false;

/**
 * 四个方位 依次判定 top right bottom left
 */
const direction = ['top', 'right', 'bottom', 'left'];

// 默认 吸附区域的宽度为 30  单位为 px
let defaultAreaSize = 30;

/**
 * 处理完 一个元素后 需要 置空
 */
let userAreaSize;

let left = 'left';
let top = 'top';
let width = 'width';
let height = 'height';
let bottom = 'bottom';
let right = 'right';

let directeLine = 'directeLine';

let directeLineWidth = 'directeLineWidth';

// 二维 坐标系
let xy = ['x', 'y'];

// 用户自定义 磁吸 元素 信息
let dataInfo;

/**
 * 当前扩展的 信息
 */
let extendedDataInfo;

//   方位影响 吸附区域 的 绝对位置
let AbsdircReflect = {
  top: { x: [left], y: [top] },
  right: { x: [left, width], y: [top] },
  bottom: { x: [left], y: [top, height] },
  left: { x: [left], y: [top] },
};

//   方位影响 吸附区域 的 取值
let dircReflect = {
  top: [-1, 0, 0, 0],
  right: [0, 1, 0, 0],
  bottom: [0, 0, 1, 0],
  left: [0, 0, 0, -1],
};

let fromtoLReflect = {
  top: { x: [0, width], y: [0, 0] },
  right: { x: [0, 0], y: [0, height] },
  bottom: { x: [0, width], y: [0, 0] },
  left: { x: [0, 0], y: [0, height] },
};

function initMagnetGrave() {
  extendedDataInfo = { data: [] };
}

// let oneSideArea = { data: ['polygonArea'], polygonArea: [] };
/**
 * 扩增 magnet 信息集
 * 有以下几种默认情况:
 * 1. 只给定 元素名称  默认四周 30px 矩形区域 为有效吸附区域
 *
 *
 * 2. 给定 元素名称 数组 按需求 计算 相应 数据情况; 如果 有相同吸附区域 按照 名称排序 依次判定
 *
 *
 * 3. 给定 元素 元素自定义区域 top right bottom left 都可以设置区域 (可以设置 多边形区域 (相对区域 后面 会计算出 实际 视窗点位)); 如果 有相同吸附区域 按 上右下左 依次判定
 *
 *
 * 4. 给定 元素名称 数组 定义元素 自定义区域 同上判定
 *
 * @param {Object} elInfo 给定的 绑定 elInfo 数据  需要绑定元素为 id 名称
 */
function extendMagnetDataInfo(elInfo) {
  // 首次调用 初始化数据 或 非 数组解析中
  if (!isArrayElInfo) {
    initMagnetGrave();
  }
  dataInfo = elInfo;
  let data = 'magnetEl';
  //   console.log(elInfo, data);
  let keyID;

  //   string 为操作主体  -- 将 array 转换成 string 进行处理
  if (toStringTypeCheck(elInfo[data], 'string')) {
    // 吸附目标元素 ID
    keyID = elInfo[data];
    // extendedDataInfo['data'].push(keyID);

    // analysisElArea(elInfo[elInfo[data]]);
    let el = document.getElementById(keyID);
    let elpo = {
      top: el.offsetTop,
      left: el.offsetLeft,
      width: el.offsetWidth,
      height: el.offsetHeight,
    };
    ObjectOnlyPushSet(extendedDataInfo, keyID, analysisElArea(elpo, keyID));
    extendedDataInfo[keyID]['elpo'] = elpo;
    extendedDataInfo[keyID]['bigReflectArea'] = bigMagnetReflectArea(keyID);

    // 处理完 一个元素后 置空 userAreaSize
    extendedDataInfo[keyID]['userAreaSize'] = userAreaSize;
    userAreaSize = undefined;
  } else if (toStringTypeCheck(elInfo[data], 'array')) {
    let eldata_c = [...elInfo[data]];
    // 启用 数组解析 进程控制 不进行初始化 extendedDataInfo
    isArrayElInfo = true;
    for (let i = 0; i < eldata_c.length; i++) {
      elInfo[data] = eldata_c[i];
      extendMagnetDataInfo(elInfo);
    }
    // 释放 数组解析 进程控制 下次调用 为 初始化 extendedDataInfo
    isArrayElInfo = false;

    console.log(extendedDataInfo);
    return extendedDataInfo;
  }

  //   在数组解析 时 禁用 数据返回
  if (!isArrayElInfo) {
    console.log(extendedDataInfo);
    return extendedDataInfo;
  }
}

/**
 * 根据元素位置  吸附区域 和 吸附位置
 *
 * 返回 实际或 填充默认的 吸附区域 和 吸附位置 信息
 * @param {Object} elpo 元素的 top left width height
 * @param {Object} keyID  元素 id
 */
function analysisElArea(elpo, keyID) {
  //   元素 周围范围 direction_i_area -- 区域位置 单元
  let direction_i_area = dataInfo[keyID];

  //   //   元素 top 和 left 以及 宽高 信息
  //   let elpo = dataInfo[keyID]['elpo'];
  console.log('eldirection: ', elpo, '\n', 'poiArea:', direction_i_area);

  //   返回对象中的 方位 关键词数组
  let poiArea = 'poiArea';

  //   方位关键字
  let key;

  let returnObj = { poiArea: [], directeLine: {} };

  // 方位上的 吸附区域
  let polygonArr;

  let fromtoL;

  //默认 四周 30px 矩形区域 -- inject func
  if (direction_i_area == undefined) {
    if (defaultArea_iFacObj.getstatus()) {
      // 需要 暴露 一些信息
      // defaultArea_iFacObj.exposeProp(elpo)
      // magent 扩增 新规范
      defaultArea_iFacObj.injected();
    } else {
      // 如果 目标元素 未定义 相关吸附 信息 则 默认为其 四周 添加 30px 的 矩形吸附区域
      for (let i = 0; i < direction.length; i++) {
        key = direction[i];

        polygonArr = {
          polygonArr: search_BigPolygon(
            leadAbsPolygon(elpo, key, buildDefaultPolygon(elpo, key))[
              'polygonArr'
            ]
          )[0],
        };

        ObjectOnlyPushSet(returnObj, key, polygonArr, poiArea);
      }
    }
  } else {
    /**
     * 当前元素的 方位
     */
    let eldirect_i;

    // 0.1 用户定义 默认吸附大小
    if (direction_i_area['areaSize'] != undefined) {
      userAreaSize = getNum(direction_i_area['areaSize']);
    }

    // 0.2 用户 定义 方位
    if (direction_i_area['direction'] != undefined) {
      for (let i = 0; i < direction_i_area['direction'].length; i++) {
        eldirect_i = direction_i_area['direction'][i];
        // 定义方位 只能在 定义过的 poiArea 中 进行更改
        if (direction.indexOf(eldirect_i) > -1) {
          ObjectOnlyPushSet(returnObj, eldirect_i, undefined, poiArea);
        }
      }
    } else {
      for (let i = 0; i < direction.length; i++) {
        eldirect_i = direction[i];
        ObjectOnlyPushSet(returnObj, eldirect_i, undefined, poiArea);
      }
    }

    if (direction_i_area[directeLineWidth] != undefined) {
      returnObj[directeLineWidth] = directeLineWidth;
    }

    // 0.21 检测 是否 有方位 上的定义 吸附区域
    for (let i = 0; i < direction.length; i++) {
      eldirect_i = direction[i];
      if (direction_i_area[eldirect_i] != undefined) {
        //  -- 最大面积的 多边形点位 数组
        polygonArr = search_BigPolygon(direction_i_area[eldirect_i])[0];

        // 确立 方位 和其 吸附区域
        let directArea_B = ObjectOnlyPushSet(
          returnObj,
          eldirect_i,
          polygonArr,
          poiArea
        );
        //  如果 添加 失败
        if (!directArea_B) {
          returnObj[eldirect_i] = polygonArr;
        }
      }
    }

    //   修正 方位 排序
    returnObj[poiArea] = sortDirection(returnObj[poiArea]);

    // 0.29 -- 补充 定义方位 但未定义 吸附区域  -- 设置 为 默认 吸附区域
    for (let i = 0; i < returnObj[poiArea].length; i++) {
      eldirect_i = returnObj[poiArea][i];
      if (returnObj[eldirect_i] == undefined) {
        polygonArr = {
          polygonArr: search_BigPolygon(
            leadAbsPolygon(
              elpo,
              eldirect_i,
              buildDefaultPolygon(elpo, eldirect_i)
            )['polygonArr']
          )[0],
        };

        returnObj[eldirect_i] = polygonArr;
      }
    }

    // 用户 定义 方位 上的 __吸附线__ 默认为 from to 直线
    for (let i = 0; i < returnObj[poiArea].length; i++) {
      eldirect_i = returnObj[poiArea][i];
      if (direction_i_area[directeLine] != undefined) {
        fromtoL = direction_i_area[directeLine][eldirect_i];
      }
      // 默认 吸附线 为 边长 如果 有 吸附距离 则 abs 吸附线
      if (fromtoL == undefined) {
        fromtoL = buildDefaultFromtoL(elpo, eldirect_i);
      }
      returnObj[directeLine][eldirect_i] = leadAbsFromtoL(
        elpo,
        eldirect_i,
        fromtoL,
        returnObj[directeLineWidth]
      );
      fromtoL = undefined;
    }
  }
  console.log(returnObj);
  return returnObj;
}

/**
 * 根据 元素位置 大小 和 定义的方位 进行 多边形的 整体偏移
 * @param {Object} elpo 元素的 top left width height
 * @param {String} key 定义方位
 * @param {Array} polygonArr 二维 多边形点位
 * @returns -- { polygonArr } 偏移后的 多边形 点位 数据
 */
function leadAbsPolygon(elpo, key, polygonArr) {
  console.log(elpo, key, polygonArr, AbsdircReflect);
  //   单个节点 坐标
  let coordi;
  //   影响 偏移 关键字
  let reflectkey;

  for (let i = 0; i < xy.length; i++) {
    for (let j = 0; j < polygonArr.length; j++) {
      coordi = polygonArr[j];
      for (let m = 0; m < AbsdircReflect[key][xy[i]].length; m++) {
        reflectkey = AbsdircReflect[key][xy[i]][m];
        coordi[i] += elpo[reflectkey];
      }
    }
  }
  console.log(polygonArr);

  return { polygonArr };
}

/**
 * 根具方位 计算出 默认边距 适应宽高 的
 * @param {Object} elpo 元素的 宽、高、上边距、左边距
 * @param {String} direct ['top', 'right', 'bottom', 'left']
 */
function buildDefaultPolygon(elpo, direct) {
  //   console.log(elpo, direct);
  let coordArr;
  let { width, height } = elpo;
  //   console.log(width, height);
  let useWidth = 1;
  let useHeight = 1;

  let W_HReflect = ['width', 'height', 'width', 'height'];

  let direc_i = direction.indexOf(direct);
  if (direc_i > -1) {
    if (W_HReflect[direc_i] == 'width') {
      useHeight = 0;
    } else {
      useWidth = 0;
    }
    direc_i = direction[direc_i];
    let areawidth = 0;

    for (let i = 0; i < dircReflect[direc_i].length; i++) {
      if (userAreaSize == undefined) {
        areawidth += defaultAreaSize * dircReflect[direc_i][i];
      } else {
        areawidth += userAreaSize * dircReflect[direc_i][i];
      }
    }

    let B0 = { x: 0, y: 0 };
    let B1 = { x: useWidth == 0 ? areawidth : width, y: 0 };
    let B2 = { x: 0, y: useHeight == 0 ? areawidth : height };
    let B3 = { x: B1.x, y: B2.y };

    coordArr = [
      [B0.x, B0.y],
      [B1.x, B1.y],
      [B2.x, B2.y],
      [B3.x, B3.y],
    ];

    console.log(coordArr);
    return coordArr;
  }
}

/**
 * 根据 元素位置 大小 和 定义的方位 进行 吸附线 的 整体偏移
 * @param {Object} elpo 元素的 top left width height
 * @param {String} key 定义方位
 * @param {Array} fromtoL 二维 吸附线点位
 * @param {Number} lineWidth 吸附线 距离 元素 边距
 * @returns -- { fromtoL } 偏移后的 吸附线 点位 数据
 */
function leadAbsFromtoL(elpo, key, fromtoL, lineWidth) {
  console.log(elpo, key, fromtoL, lineWidth, fromtoLReflect);
  let xy_i;
  let reflect_i;
  let coord_i;
  for (let i = 0; i < xy.length; i++) {
    xy_i = xy[i];
    for (let j = 0; j < AbsdircReflect[key][xy_i].length; j++) {
      reflect_i = AbsdircReflect[key][xy_i][j];
      for (let m = 0; m < fromtoL.length; m++) {
        coord_i = fromtoL[m];
        coord_i[i] += elpo[reflect_i];
      }
    }
  }
  return fromtoL;
}

/**
 * 根据 元素的 大小 确立 fromtoL 的 二维数据
 * @param {Object} elpo 元素的 top left width height
 * @param {String} key 定义方位
 * @returns {Array} -- 两个 点位数据
 */
function buildDefaultFromtoL(elpo, key) {
  let returnArr = [];
  let reflect = fromtoLReflect[key];
  if (direction.indexOf(key) > -1) {
    for (let i = 0; i < 2; i++) {
      let x = reflect['x'][i] == 0 ? 0 : elpo[reflect['x'][i]];
      let y = reflect['y'][i] == 0 ? 0 : elpo[reflect['y'][i]];

      returnArr[i] = [x, y];
    }
    return returnArr;
  }
}

/**
 * 计算出 该 元素的 最大 吸附 矩形区域
 * @param {String} elID 目标元素 id 名称
 * @returns
 */
function bigMagnetReflectArea(elID) {
  let BMEA_Reflect = {
    top: ['min', 'y'],
    left: ['min', 'x'],
    bottom: ['max', 'y'],
    right: ['max', 'x'],
  };
  let bigAreaObj = {};
  //   返回值 的 最大 吸附区域的 矩形 坐标 数组
  let coordArr;
  let key;
  for (let i = 0; i < direction.length; i++) {
    key = direction[i];
    if (BMEA_Reflect[key][0] == 'min') {
      bigAreaObj[key] = getMinCoord_a(elID, key, BMEA_Reflect[key][1]);
    } else {
      bigAreaObj[key] = getMaxCoord_a(elID, key, BMEA_Reflect[key][1]);
    }
  }
  let B0 = { x: bigAreaObj[left], y: bigAreaObj[top] };
  let B1 = { x: bigAreaObj[right], y: bigAreaObj[top] };
  let B2 = { x: bigAreaObj[right], y: bigAreaObj[bottom] };
  let B3 = { x: bigAreaObj[left], y: bigAreaObj[bottom] };

  coordArr = [
    [B0.x, B0.y],
    [B1.x, B1.y],
    [B2.x, B2.y],
    [B3.x, B3.y],
  ];
  return coordArr;
}

/**
 * 获取 方位 吸附区域中 的 最大 X Y 的 坐标值
 * @param {String} elID 目标元素的 ID 名称
 * @param {String} key 方位
 * @param {x|y} xOry [x,y] x 坐标系 或 y 坐标系
 * @returns 最大 相关 目标元素 的 方位 的 相关坐标系值
 */
function getMaxCoord_a(elID, key, xOry) {
  let xy_i = xy.indexOf(xOry);
  let Max;

  //   扩展后的 元素 方位
  let exedElDirection = extendedDataInfo[elID][key];
  //如果当前方位 上没有 吸附区域 则 默认为 方位的 偏移量
  if (exedElDirection != undefined) {
    Max = exedElDirection['polygonArr'][0][xy_i];
  } else {
    Max = 0;
    for (let i = 0; i < AbsdircReflect[key].length; i++) {
      // 偏移 量
      let excu_j = exedElDirection['elpo'][AbsdircReflect[key][i]];
      Max += excu_j;
    }
    return Max;
  }

  let coordi;
  for (let i = 1; i < exedElDirection['polygonArr'].length; i++) {
    coordi = [...exedElDirection['polygonArr'][i]];
    Max = Max < coordi[xy_i] ? coordi[xy_i] : Max;
  }
  return Max;
}

/**
 * 获取 方位 吸附区域中 的 最小 X Y 的 坐标值
 * @param {String} elID 目标元素的 ID 名称
 * @param {String} key 方位
 * @param {x|y} xOry [x,y] x 坐标系 或 y 坐标系
 * @returns 最小 相关 目标元素 的 方位 的 相关坐标系值
 */
function getMinCoord_a(elID, key, xOry) {
  let xy_i = xy.indexOf(xOry);
  let Min;

  //   扩展后的 元素 方位
  let exedElDirection = extendedDataInfo[elID][key];
  //如果当前方位 上没有 吸附区域 则 默认为 方位的 偏移量
  if (exedElDirection != undefined) {
    Min = exedElDirection['polygonArr'][0][xy_i];
  } else {
    Min = 0;
    for (let i = 0; i < AbsdircReflect[key].length; i++) {
      // 偏移 量
      let excu_j = exedElDirection['elpo'][AbsdircReflect[key][i]];
      Min += excu_j;
    }
    return Min;
  }
  let coordi;
  for (let i = 1; i < exedElDirection['polygonArr'].length; i++) {
    coordi = exedElDirection['polygonArr'][i];
    Min = Min > coordi[xy_i] ? coordi[xy_i] : Min;
  }
  return Min;
}

/**
 * 排序 方位数组
 * @param {Array} directionArr 方位 的 数组 [direction]
 */
function sortDirection(directionArr) {
  let returnArr = [];
  for (let i = 0; i < direction.length; i++) {
    if (directionArr.indexOf(direction[i] > -1)) {
      returnArr.push(direction[i]);
    }
  }
  return returnArr;
}

export { extendMagnetDataInfo };
